package team.seekers.hula.course.course.service;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import team.seekers.hula.common.entity.PageResult;
import team.seekers.hula.common.entity.result.ApiExceptionEnum;
import team.seekers.hula.common.entity.enums.course.CourseSortTypeEnum;
import team.seekers.hula.common.utils.AssertUtils;
import team.seekers.hula.course.course.dao.CourseDao;
import team.seekers.hula.course.course.entity.dao.CourseDO;
import team.seekers.hula.course.course.entity.dto.CourseListReqDTO;
import team.seekers.hula.course.course.entity.dto.CourseOrderInfoDTO;
import team.seekers.hula.course.course.entity.vo.CourseBasicInfoVO;
import team.seekers.hula.course.course.entity.vo.CourseInfoVO;
import team.seekers.hula.course.course.entity.vo.CourseListVO;
import team.seekers.hula.course.course.entity.vo.CourseProgressListVO;
import team.seekers.hula.course.courseUser.entity.dto.CourseUserListDTO;
import team.seekers.hula.course.courseUser.entity.vo.CourseUserListVO;
import team.seekers.hula.course.courseUser.entity.vo.CourseUserManageInfoVO;
import team.seekers.hula.course.courseUser.entity.vo.CourseUserManageListVO;
import team.seekers.hula.course.courseUser.service.CourseUserService;
import team.seekers.hula.course.resource.sectionContent.entity.dto.SectionContentListDTO;
import team.seekers.hula.course.resource.sectionContent.service.SectionContentService;
import team.seekers.hula.course.structure.chapter.dao.ChapterDao;
import team.seekers.hula.course.structure.chapter.entity.dao.ChapterDO;
import team.seekers.hula.course.structure.chapter.entity.dto.ChapterQueryListDTO;
import team.seekers.hula.course.structure.chapter.service.ChapterService;
import team.seekers.hula.course.structure.section.dao.SectionDao;
import team.seekers.hula.course.structure.section.entity.dao.SectionDO;
import team.seekers.hula.course.structure.section.service.SectionService;
import team.seekers.hula.auth.service.MindUtils;
import team.seekers.hula.user.user.service.UserService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class CourseService {

    @Autowired
    private CourseDao courseDao;

    @Autowired
    private SectionContentService sectionContentService;

    @Autowired
    private ChapterService chapterService;

    @Autowired
    private CourseUserService courseUserService;

    @Autowired
    private SectionDao sectionDao;

    @Autowired
    private ChapterDao chapterDao;

    @Autowired
    private UserService userService;

    @Autowired
    private SectionService sectionService;

    /**
     * 查看知桨详细信息
     */
    public CourseInfoVO getCourseInfo(String courseId) {
        CourseDO courseDO = courseDao.getById(courseId);
        CourseInfoVO courseInfoVO = courseDO.toVO();

        // TODO 冗余课程章数和节数
        courseInfoVO.setSectionCount(sectionDao.lambdaQuery().eq(SectionDO::getCourseId,courseId).count());
        courseInfoVO.setChapterCount(chapterDao.lambdaQuery().eq(ChapterDO::getCourseId,courseId).count());
        courseInfoVO.setUserCount(courseUserService.countBuy(courseId));
        // 作者信息
        if(MindUtils.isLogin()){
            String userId = MindUtils.getUserId();

            courseInfoVO.setUserInfo(userService.getFollowInfoVO(courseDO.getUserId(),userId));

            ArrayList<String> courseIds = new ArrayList<>();
            courseIds.add(courseDO.getId());
            Map<String, Boolean> userBuyStatusMap = courseUserService.queryBuyStatusByCourseIdsAndUserId(courseIds,userId);
            Map<String, Boolean> userFixedStatusMap = courseUserService.queryFixedStatusByCourseIdsAndUserId(courseIds,userId);

            if(!userBuyStatusMap.get(courseId)){
                return courseInfoVO;
            }

            // 如果已加入，则查询学习信息

            // 设置购买和收藏状态
            courseInfoVO.setIsBuy(userBuyStatusMap.get(courseInfoVO.getId()));
            courseInfoVO.setIsFixed(userFixedStatusMap.get(courseInfoVO.getId()));
//        courseVO.setIsCollect(userService.queryAllCollectCourse(userId).contains(courseId));


            // 上次学习信息
            CourseUserManageInfoVO courseUser = courseUserService.getProgressInfoByCourseUserId(courseInfoVO.getId(), MindUtils.getUserId());
            courseInfoVO.setLastSectionId(courseUser.getLastSectionId());
            courseInfoVO.setLastSectionName(courseUser.getLastSectionName());
            courseInfoVO.setLastProgress(courseUser.getLastProgress());
            courseInfoVO.setProgress(courseUser.getProgress());
            courseInfoVO.setIsBuy(true);
        }else {
            courseInfoVO.setUserInfo(userService.getFollowInfoVO(courseDO.getUserId(),null));
        }
        return courseInfoVO;
    }

    /**
     * 根据id集合查询知桨
     */
    public List<CourseListVO> listByIds(List<String> courseIds) {
        List<CourseDO> list = courseDao.lambdaQuery().select(
                CourseDO::getId,
                CourseDO::getName,
                CourseDO::getCover,
                CourseDO::getPrice,
                CourseDO::getStatus
        ).in(CourseDO::getId, courseIds).list();

//        List<String> courseIds = new ArrayList<>();
//        list.forEach(CourseDO -> courseIds.add(CourseDO.getId()));

        // 获取是否购买集合
//        Map<Long, Boolean> userStatusMap = courseUserService.queryBuyStatusByCourseIdsAndUserId(courseIds,userId,0);

        // 获取是否收藏
//        List<Long> allCollectCourseList = userClient.queryAllCollectCourse(userId);

        // 获取几个压场子的课时
//        Map<String, List<SectionContentListVO>> fourSectionContentsMap = sectionContentService.mapFourSectionContentByCourseIds(courseIds);

        return list.stream().map(entity -> {
            CourseListVO vo = entity.toPageVO();
//            vo.setIsBuy(userStatusMap.get(entity.getId()));
//            vo.setIsCollect(allCollectCourseList.contains(entity.getId()));
//            vo.setContentI(fourSectionContentsMap.get(entity.getId()));
            vo.setSectionCount(sectionDao.lambdaQuery().eq(SectionDO::getCourseId,entity.getId()).count());
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 分页查询知桨
     */
    public PageResult<CourseListVO> page(CourseListReqDTO req) {
        LambdaQueryChainWrapper<CourseDO> query = courseDao.lambdaQuery().select();
        if (StringUtils.isNotBlank(req.getName())) {
            query.and(o1 -> o1.like(CourseDO::getName, req.getName())
                    .or().like(CourseDO::getDescription, req.getName()));
        }

        if(req.getStatus() != null){
            query.eq(CourseDO::getStatus,req.getStatus());
        }else {
            query.ge(CourseDO::getStatus,1);
        }

        if(req.getSortType() != null){
            switch (CourseSortTypeEnum.getByCode(req.getSortType())) {
                case PRICE:
                    query.orderByDesc(CourseDO::getPrice);
                    break;
                case STUDENT_COUNT:
//                    query.orderByDesc(CourseDO::getParticipantNum);
                    break;
                case OTHER:
                case COMPREHENSIVENESS:
                case TIME:
                    query.orderByDesc(CourseDO::getGmtCreate);
                    break;
                default:
                    break;
            }
        }

        Page<CourseDO> page = query.page(new Page<>(req.getPageNow(), req.getPageSize()));

//        List<String> ids = new ArrayList<>();
//        page.getRecords().forEach(o1 -> ids.add(o1.getId()));

        // 获取是否购买集合
//        Map<Long, Boolean> userStatusMap = courseUserService.queryBuyStatusByCourseIdsAndUserId(ids,userId,0);

        // 获取是否收藏
//        List<Long> allCollectCourseList = userClient.queryAllCollectCourse(userId);

        // 获取几个压场子的课时
//        Map<String, List<SectionContentListVO>> fourSectionContentsMap = sectionContentService.mapFourSectionContentByCourseIds(ids);

        List<CourseListVO> pageVOS = page.getRecords().stream().map(entity -> {
            CourseListVO vo = entity.toPageVO();
//            vo.setIsBuy(userStatusMap.get(entity.getId()));
//            vo.setIsCollect(allCollectCourseList.contains(entity.getId()));
//            vo.setContents(fourSectionContentsMap.get(entity.getId()));
            vo.setSectionCount(sectionDao.lambdaQuery().eq(SectionDO::getCourseId,entity.getId()).count());
            return vo;
        }).collect(Collectors.toList());
        return new PageResult<>(page.getPages(), pageVOS);
    }

    /**
     * 分页查询知桨
     */
    public PageResult<CourseProgressListVO> pageMine(CourseListReqDTO req) {
        LambdaQueryChainWrapper<CourseDO> query = courseDao.lambdaQuery().select(
                CourseDO::getId,
                CourseDO::getName,
                CourseDO::getCover,
                CourseDO::getDescription
        );
        if (StringUtils.isNotBlank(req.getName())) {
            query.and(o1 -> o1.like(CourseDO::getName, req.getName())
                    .or().like(CourseDO::getDescription, req.getName()));
        }

        Map<String, CourseUserListVO> map = courseUserService
                .mapVOByUserId(CourseUserListDTO.builder().userId(req.getUserId()).build());

        if(map.keySet().size() == 0){
            return new PageResult<>();
        }

        query.in(CourseDO::getId,map.keySet());

        Page<CourseDO> page = query.page(new Page<>(req.getPageNow(), req.getPageSize()));

        List<String> ids = new ArrayList<>();
        page.getRecords().forEach(o1 -> ids.add(o1.getId()));

        List<CourseProgressListVO> pageVOS = page.getRecords().stream().map(entity -> {
            CourseProgressListVO courseProgressListVO = new CourseProgressListVO();
            BeanUtils.copyProperties(entity,courseProgressListVO);

            // 上次学习信息
            CourseUserListVO courseUser = map.get(entity.getId());
            if(StringUtils.isNotBlank(courseUser.getLastSectionId())){
                courseProgressListVO.setLastSectionId(courseUser.getLastSectionId());
                courseProgressListVO.setLastSectionName(sectionService.getNameById(courseUser.getLastSectionId()));
            }else{
                courseProgressListVO.setLastSectionId(sectionService.getFirstId(entity.getId()));
                courseProgressListVO.setLastSectionName("暂无学习记录");
            }

            courseProgressListVO.setProgress(courseUser.getProgress());

            return courseProgressListVO;
        }).collect(Collectors.toList());
        return new PageResult<>(page.getPages(), pageVOS);
    }

    /**
     * 查看知桨目录（无学习情况）
     */
    public List<ChapterQueryListDTO> getSimpleCourseDirs(String courseId) {
        AssertUtils.notNull(courseId, ApiExceptionEnum.PARAM_NOT_VALID);
        return chapterService.getSimpleCourseDirsByCourseId(courseId);
    }

    /**
     * 查看知桨目录（有学习情况）
     */
    public List<ChapterQueryListDTO> getDetailCourseDirs(String courseId, String userId) {
        AssertUtils.notNull(courseId, ApiExceptionEnum.PARAM_NOT_VALID);
        return chapterService.getDetailCourseDirsByCourseId(courseId, userId);
    }






    public Integer queryProgressByCourseIdAndUserId(String courseId, String userId) {
        // 获取所有节
        List<SectionDO> sectionDOList = sectionDao.lambdaQuery().select(
                SectionDO::getId
        ).eq(SectionDO::getCourseId, courseId).list();

        Integer sectionNum = sectionDOList.size();
        Integer sectionLearnedNum = 0;
        // 计算已学节数
        for (SectionDO sectionDO : sectionDOList) {
            List<SectionContentListDTO> sectionContentListDTOS = sectionContentService.querySectionContentsBySectionIdWithStatus(sectionDO.getId(),userId);
            boolean isLearned = true;
            if(sectionContentListDTOS == null || sectionContentListDTOS.size() == 0){
                continue;
            }
            for (SectionContentListDTO sectionContentListDTO : sectionContentListDTOS) {
                if(sectionContentListDTO.getProgress() < 100){
                    isLearned = false;
                    break;
                }
            }
            if(isLearned){
                sectionLearnedNum++;
            }
        }
        return sectionLearnedNum*100/sectionNum;
    }




    public String idToName(String courseId) {
        return courseDao.getById(courseId).getName();
    }

    public String idToDescription(String courseId) {
        return courseDao.getById(courseId).getDescription();
    }

    public List<String> idToChapterIds(String courseId) {
        return chapterService.queryChapterIdsByCourseId(courseId);
    }


    public List<CourseUserListDTO> idsToCourseUserListDTOList(List<String> courseIds) {
        List<CourseDO> courseDOList = courseDao.listByIds(courseIds);
        ArrayList<CourseUserListDTO> courseUserListDTOS = new ArrayList<>();
        for (CourseDO courseDO : courseDOList) {
            CourseUserListDTO courseListDTO = new CourseUserListDTO();
            BeanUtils.copyProperties(courseDO,courseListDTO);
//            courseListDTO.setSectionCount(sectionDao.lambdaQuery().eq(SectionDO::getCourseId,courseDO.getId()).count());
            courseUserListDTOS.add(courseListDTO);
        }
        return courseUserListDTOS;
    }

    public List<CourseUserListDTO> idsAndUserIdToCourseInfoAndProcessListDTOList(List<String> courseIds, String userId) {
        ArrayList<CourseUserListDTO> courseUserListDTOS = new ArrayList<>();

        if(courseIds.size() == 0){
            return new ArrayList<>();
        }
        List<CourseDO> courseDOList = courseDao.listByIds(courseIds);
        for (CourseDO courseDO : courseDOList) {
            CourseUserListDTO courseListDTO = new CourseUserListDTO();
            BeanUtils.copyProperties(courseDO,courseListDTO);

            // 获取所有节id
            List<SectionDO> sectionDOList = sectionDao.lambdaQuery().select(
                    SectionDO::getId
            ).eq(SectionDO::getCourseId, courseDO.getId()).list();

            ArrayList<String> sectionIds = new ArrayList<>();
            // 计算已学节数并找到上一次学习的最后节内容
            for (SectionDO sectionDO : sectionDOList) {
                sectionIds.add(sectionDO.getId());
            }

//            CourseLearnedProcessDTO courseLearnedProcessDTO = sectionContentService.queryLearnProcessBySectionIds(sectionIds,userId);
//
//
//
//            courseListDTO.setSectionCount(courseLearnedProcessDTO.getSectionContentNum());
//            courseListDTO.setSectionLearnedCount(courseLearnedProcessDTO.getSectionContentLearnedNum());
//            courseListDTO.setLastSectionContentId(courseLearnedProcessDTO.getLastSectionId());
//            courseListDTO.setLastSectionContentName(courseLearnedProcessDTO.getLastSectionContentName());

            courseUserListDTOS.add(courseListDTO);
        }
        return courseUserListDTOS;
    }


    public Map<String, String> idsToNameMap(List<Long> courseIds) {
        List<CourseDO> list = courseDao.lambdaQuery().select(
                CourseDO::getId,
                CourseDO::getName
        ).in(CourseDO::getId, courseIds).list();

        HashMap<String, String> longStringHashMap = new HashMap<>();
        for (CourseDO courseDO : list) {
            longStringHashMap.put(courseDO.getId(),courseDO.getName());
        }

        return longStringHashMap;
    }

    public HashMap<String, CourseOrderInfoDTO> idsToCourseOrderInfoMap(ArrayList<String> courseIds) {
        List<CourseDO> list = courseDao.lambdaQuery().select(
                CourseDO::getId,
                CourseDO::getName,
                CourseDO::getCover
        ).in(CourseDO::getId, courseIds).list();

        HashMap<String, CourseOrderInfoDTO> longStringHashMap = new HashMap<>();
        for (CourseDO courseDO : list) {
            CourseOrderInfoDTO courseOrderInfoDTO = new CourseOrderInfoDTO();
            BeanUtils.copyProperties(courseDO,courseOrderInfoDTO);
            longStringHashMap.put(courseDO.getId(),courseOrderInfoDTO);
        }

        return longStringHashMap;
    }

    public List<CourseListVO> listFixed() {
        // 获取常驻
        List<String> courseIds =  courseUserService.getFixedCourseIds(MindUtils.getUserId());
        if(courseIds == null || courseIds.isEmpty()){
            return new ArrayList<>();
        }else {
            List<CourseDO> islandDOList = courseDao.lambdaQuery().in(CourseDO::getId, courseIds).list();
            List<CourseListVO> courseListVOS = CourseDO.DOListToVOList(islandDOList);
            // 获取学习进度
            Map<String, Integer> progressMap = courseUserService.mapProgressByCourseIds(courseIds,MindUtils.getUserId());
            for (CourseListVO courseListVO : courseListVOS) {
                courseListVO.setProgress(progressMap.get(courseListVO.getId()));
            }
            return courseListVOS;
        }
    }


    public List<CourseListVO> listPush() {
        // TODO 获取推荐
        LambdaQueryChainWrapper<CourseDO> lambdaQuery = courseDao.lambdaQuery();

        if(MindUtils.isLogin()){
            CourseUserListDTO courseUserListDTO = new CourseUserListDTO();
            courseUserListDTO.setUserId(MindUtils.getUserId());
            Map<String, CourseUserManageListVO> userMap = courseUserService.mapManageVOByUserIdAndCourseIds(courseUserListDTO);

            ArrayList<String> joinedCourseIds = new ArrayList<>(userMap.keySet());
            if(!joinedCourseIds.isEmpty()){
                lambdaQuery.notIn(CourseDO::getId,joinedCourseIds);
            }
        }

        return CourseDO.DOListToVOList(lambdaQuery.list());
    }

    public Map<String, CourseBasicInfoVO> idsMapCourseBasicInfo(List<String> courseIds) {
        List<CourseDO> courseDOList = courseDao.lambdaQuery().select(
                CourseDO::getId,
                CourseDO::getName,
                CourseDO::getCover,
                CourseDO::getDescription
        ).in(CourseDO::getId, courseIds).list();

        HashMap<String, CourseBasicInfoVO> map = new HashMap<>();

        for (CourseDO courseDO : courseDOList) {
            CourseBasicInfoVO courseBasicInfoVO = new CourseBasicInfoVO();
            BeanUtils.copyProperties(courseDO,courseBasicInfoVO);
            map.put(courseBasicInfoVO.getId(),courseBasicInfoVO);
        }

        return map;
    }

    public List<CourseBasicInfoVO> getCourseBasicInfoVOList(List<String> courseIds) {
        if(courseIds.size() > 0){
            List<CourseDO> courseDOList = courseDao.lambdaQuery().select(
                    CourseDO::getId,
                    CourseDO::getName,
                    CourseDO::getCover,
                    CourseDO::getDescription
            ).in(CourseDO::getId, courseIds).list();

            ArrayList<CourseBasicInfoVO> list = new ArrayList<>();
            for (CourseDO courseDO : courseDOList) {
                CourseBasicInfoVO courseBasicInfoVO = new CourseBasicInfoVO();
                BeanUtils.copyProperties(courseDO,courseBasicInfoVO);
                list.add(courseBasicInfoVO);
            }
            return list;
        }else{
            return new ArrayList<>();
        }
    }
}
